package org.iabako.server.mail;

import org.apache.log4j.Logger;
import org.iabako.server.conf.AppConf;
import org.iabako.server.serviceimpl.security.SessionUser;
import org.iabako.server.tools.BundleMessages;
import org.iabako.shared.entity.user.Enterprise;
import org.iabako.shared.tools.GenericTools;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URISyntaxException;
import java.net.URL;

/**
 * Created by jose on 10/12/14.
 */

@Component
public class IabakoMailSender {

    static Logger log = Logger.getLogger(IabakoMailSender.class.getName());

    @Autowired
    private AppConf appConf;
    @Autowired
    BundleMessages messages;

    @Autowired
    private SessionUser sessionUser;

    public boolean sendMail(IabakoMailHelper iabakoMailHelper) throws MailException {
        if (GenericTools.isEmpty(iabakoMailHelper.getTo(),
                iabakoMailHelper.getSubject(),
                iabakoMailHelper.getBody())) {
            return false;
        }

        log.info("Sending Email...");

        JavaMailSenderImpl sender = new JavaMailSenderImpl();
        MimeMessage message = sender.createMimeMessage();

        MimeMessageHelper helper;
        try {
            helper = new MimeMessageHelper(message, true, "UTF-8");

            String from = iabakoMailHelper.isNoReplyEmail() ? appConf.getNoReplyEmail() : iabakoMailHelper.getFrom();
            helper.setFrom(from, iabakoMailHelper.getFromPersonal() != null ?
                    iabakoMailHelper.getFromPersonal() : iabakoMailHelper.getFrom());

            if (iabakoMailHelper.getTo().size() == 1) {
                helper.addTo(iabakoMailHelper.getTo().get(0));
            } else {
                for (String to : iabakoMailHelper.getTo()) {
                    helper.addBcc(to);
                }
            }

            helper.setSubject(iabakoMailHelper.getSubject());

            addAttachments(iabakoMailHelper, helper);

            boolean isIabakoMailFormat = !iabakoMailHelper.isDisableIabakoLogo();

            String htmlContent = getHtmlContent(isIabakoMailFormat);
            StringBuilder htmlBody = new StringBuilder();

            Enterprise enterprise;
            try {
                enterprise = sessionUser.getUser() != null ? sessionUser.getUser().getEnterprise() : null;
            } catch (BeanCreationException exception) {
                enterprise = iabakoMailHelper.getEnterprise();
            }
            enterprise = enterprise != null && enterprise.getParentEnterprise() != null ? enterprise.getParentEnterprise() : enterprise;

            boolean hasEnterpriseLogo = iabakoMailHelper.isAddEnterpriseLogo() && enterprise != null && enterprise.getLogo() != null;
            boolean hasLogo = !iabakoMailHelper.isDisableIabakoLogo() || hasEnterpriseLogo;

            if (hasLogo) {
                InputStream inputStream;
                if (hasEnterpriseLogo) {
                    inputStream = new ByteArrayInputStream(enterprise.getLogo());
                } else {
                    URL logoImage = this.getClass().getClassLoader().getResource("/org/iabako/public/logo.png");
                    inputStream = new FileInputStream(logoImage.getFile());
                }
                BufferedImage image = ImageIO.read(inputStream);
                int width = image.getWidth();
                int height = image.getHeight();

                String logoHtml = "<img src='cid:logo' alt='' style='" + GenericTools.getHtmlStyleForEnterpriseLogo(width, height) + "'/>";
                logoHtml = isIabakoMailFormat ? "<center>" + logoHtml + "</center>" : logoHtml;
                htmlBody = new StringBuilder(logoHtml + "<br/><br/><br/>");
            }

            StringBuilder txtBody = new StringBuilder(iabakoMailHelper.getBody());
            if (iabakoMailHelper.getTemplate() == null) {
                htmlBody.append(iabakoMailHelper.getBody().replace("\n", "<br/>"));
            } else {
                htmlBody.append(iabakoMailHelper.getTemplate().getHtmlBody());
            }

            htmlBody.append("<br/><br/>");
            txtBody.append("\n\n");

            if (!iabakoMailHelper.getDisableDefaultFooter()) {
                htmlBody.append(getFooter());

                txtBody.append(getFooter().replace("<br/>", "\n")
                        .replace("<hr/>", "-------------------------------------------------------------\n"));
            }

            if (iabakoMailHelper.isNoReplyEmail()) {
                htmlBody.append(getNoReplyFooter(enterprise));
            }

            if (iabakoMailHelper.isEnablePoweredByFooter()) {
                htmlBody.append(getPoweredByFooter());
            }

            helper.setText(txtBody.toString(), htmlContent.replace("_html_body_content_", htmlBody.toString()));

            Resource res = null;

            if (!iabakoMailHelper.isDisableIabakoLogo()) {
                URL logoImage = this.getClass().getClassLoader().getResource("/org/iabako/public/logo.png");
                res = new FileSystemResource(new File(logoImage.toURI()));
                helper.addInline("logo", res);
            }

            if (hasEnterpriseLogo) {
                res = new ByteArrayResource(enterprise.getLogo());
                helper.addInline("logo", res, enterprise.getContentTypeLogo());
            }

            sender.send(message);

            if (res != null && res.getInputStream() != null) {
                res.getInputStream().close();
            }

            return true;

        } catch (MessagingException e) {
            log.error(e.getMessage(), e);
        } catch (UnsupportedEncodingException e) {
            log.error(e.getMessage(), e);
        } catch (URISyntaxException e) {
            log.error(e.getMessage(), e);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        return false;
    }

    private String getHtmlContent(boolean isIabakoMailFormat) {
        if (isIabakoMailFormat) {
            StringBuilder sb = new StringBuilder("<html><body>");
            sb.append("<div style='width:100%; background-color:#ebebeb;padding:20px 0px;color:#555'>");
            sb.append("<center><div style='max-width:600px; width:90%; margin: auto;background-color: white;padding: 10px 30px;'>");
            sb.append("<div style='text-align:left;'>_html_body_content_</div>");
            sb.append("</div></center></div></body></html>");
            return sb.toString();
        } else {
            return "<html><body>_html_body_content_</body></html>";
        }
    }

    private void addAttachments(IabakoMailHelper iabakoMailHelper, MimeMessageHelper helper) throws MessagingException {
        for (String attachment : iabakoMailHelper.getAttachments().keySet()) {
            helper.addAttachment(attachment, iabakoMailHelper.getAttachments().get(attachment));
        }
    }

    private String getFooter() {
        String separator = "<br/><hr/>";
        StringBuilder footer = new StringBuilder(separator);
        footer.append("IABAKO | ").append(appConf.getServerUrl()).append(separator);
        return footer.toString();
    }

    private String getNoReplyFooter(Enterprise enterprise) {
        String separator = "<br/><hr/>";
        StringBuilder footer = new StringBuilder(separator);
        footer.append(messages.getLabel(enterprise.getLanguage(), "no_reply_mail_footer", enterprise.getName()) + " ");
        footer.append("<span style='color:#0088CC; text-decoration:underline;'>").append(enterprise.getEmail()).append("</span><br/>");
        return footer.toString();
    }

    private String getPoweredByFooter() {
        String separator = "<br/><div style='font-size:10px'><hr/>";
        StringBuilder footer = new StringBuilder(separator);
        footer.append("Powered by IABAKO | <a href='")
                .append(appConf.getServerUrl())
                .append("'>")
                .append(appConf.getServerUrl()).append("</a></div>");
        return footer.toString();
    }
}
